package com.sc.nft.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.annotation.UserLogin;
import com.sc.nft.controller.request.ExchangeRequest;
import com.sc.nft.controller.request.IdRequest;
import com.sc.nft.controller.vo.DrawPrizeVO;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.QueryBoxConditionDTO;
import com.sc.nft.entity.req.TaskBoxPoolRequest;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.BoxTakePoolConvertScenarioEnum;
import com.sc.nft.enums.EquityPropsTypeEnum;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.enums.task.TaskPrizeTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.BoxTakeConversionConditionService;
import com.sc.nft.service.NftMallService;
import com.sc.nft.service.TaskService;
import com.sc.nft.service.UserEquityPropsService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.RoundingMode;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 任务控制器
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/task")
@Api(tags = "任务页面")
public class TaskController {
    private final TaskService taskService;


    private final BoxTakePoolDao boxTakePoolDao;

    private final NftMallService nftMallService;

    private final EquityPropsDao equityPropsDao;

    private final UserEquityPropsService userEquityPropsService;

    private final Redisson redisson;


    private final UserCreatorInfoDao userCreatorInfoDao;


    private final DigitalCollectionProductInfoDao digitalCollectionProductInfoDao;

    private final BoxTakeConversionConditionService boxTakeConversionConditionService;

    private final UserCollectionDao userCollectionDao;

    @ApiOperation(value = "任务列表", notes = "任务列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/taskList", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<TaskListVO>> getUserDaoDetails() {
        return Result.success(taskService.getUserTaskListVO(UserPool.getUser()));
    }

    @ApiOperation(value = "商户任务列表", notes = "任务列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/taskMerchantList", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<TaskListVO>> getUserMerchantTaskListVO() {
        return Result.success(taskService.getUserMerchantTaskListVO(UserPool.getUser()));
    }

    @ApiOperation(value = "待领取奖励列表", notes = "待领取奖励列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/rewardList", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<DrawPrizeVO>> getRewardList() {
        List<TaskDrawPrize> taskPrize = taskService.getTaskPrize(UserPool.getUser());
        List<DrawPrizeVO> vos = Lists.newArrayList();
        for (TaskDrawPrize taskDrawPrize : taskPrize) {
            DrawPrizeVO vo = BeanUtil.toBean(taskDrawPrize, DrawPrizeVO.class);
            if (vo.getPrizeType() == TaskPrizeTypeEnum.PROPS) {
                EquityProps equityProps = equityPropsDao.getById(taskDrawPrize.getEquityId());
                vo.setPrizeCount(taskDrawPrize.getPrizeCount().setScale(0, RoundingMode.HALF_UP).toPlainString());
                vo.setPropsName(equityProps.getFirstTitle());
            } else if (vo.getPrizeType() == TaskPrizeTypeEnum.INTEGRAL) {
                vo.setPropsName("积分");
            }
            vos.add(vo);
        }
        return Result.success(vos);
    }


    @ApiOperation(value = "领取奖励", notes = "领取奖励", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/drawPrize", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result drawPrize(@RequestBody @Valid IdRequest request) {

        String key = StrUtil.format("{}:{}", RedisKeyEnum.DRAW_PRIZE_LOCK.getKey(), request.getId());
        RLock lock = redisson.getLock(key);
        try {
            boolean b = lock.tryLock(3, TimeUnit.SECONDS);
            if (!b) {
                return Result.fail("请勿频繁点击");
            }
            taskService.drawPrize(UserPool.getUser(), request.getId());
        } catch (InterruptedException e) {
            return Result.fail("请勿频繁点击");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

//    @ApiOperation(value = "完成广告任务", notes = "完成广告任务", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
//    @PostMapping(value = "/finishAdTask", produces = MediaType.APPLICATION_JSON_VALUE)
//    @UserLogin
//    public Result finishAdTask(@RequestBody @Valid FinishAdTaskRequest request) {
//        if(taskPlanRecordDao.selectByLinkId(TaskTypeEnum.AD,request.getAdId())>0){
//            log.warn("广告任务已完成:{}",request.getAdId());
//            return Result.success();
//        }
//        taskService.finishTask(UserPool.getUser(), TaskTypeEnum.AD, request.getAdId(),null);
//        return Result.success();
//    }


    @PostMapping(value = "/boxPoolList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "盲盒抽奖池列表", notes = "盲盒抽奖池列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<BoxPoolVO> boxPoolList(@RequestBody @Valid TaskBoxPoolRequest request) {
        if (Objects.equals(request.getConvertScenario(), BoxTakePoolConvertScenarioEnum.DAO_CONVERT)
                && Objects.isNull(request.getDaoId())) {
            throw new GlobalRunTimeException("品牌不能为空");
        }
        Page<BoxPoolVO> boxPoolVOPage = boxTakePoolDao.boxPoolWebPage(true, null, request.getConvertScenario(), request.getDaoId(), request.getPageNo(), request.getPageSize());
        boxPoolVOPage.getRecords().forEach(boxPoolVO -> {
            QueryBoxConditionDTO queryBoxConditionDTO = new QueryBoxConditionDTO();
            queryBoxConditionDTO.setBoxId(boxPoolVO.getId());
            List<QueryBoxConditionVO> queryBoxConditionVOS = boxTakeConversionConditionService.queryBoxCondition(queryBoxConditionDTO);
            QueryWebBoxConditionPackagingVO queryWebBoxConditionPackagingVO = new QueryWebBoxConditionPackagingVO();
            queryWebBoxConditionPackagingVO.setQueryBoxCondition(BeanUtil.copyToList(queryBoxConditionVOS, QueryWebBoxConditionVO.class));
            // 所需藏品的数据
            queryWebBoxConditionPackagingVO.nftConfiguration(null);
            boxPoolVO.setNftExclusive(BeanUtil.isNotEmpty(queryWebBoxConditionPackagingVO.getQueryBoxConditionCollection()) ? queryWebBoxConditionPackagingVO.getQueryBoxConditionCollection().getName() : null);
        });
        return PageResult.success(boxPoolVOPage);
    }


    @PostMapping(value = "/exchange", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "盲盒兑换", notes = "盲盒兑换", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result boxPoolList(@RequestBody ExchangeRequest request) throws GlobalRunTimeException {
        String key = StrUtil.format("{}:{}", RedisKeyEnum.BOX_POOL_LIST.getKey(), request.getId());
        RLock lock = redisson.getLock(key);
        try {
            boolean b = lock.tryLock(3, TimeUnit.SECONDS);
            if (!b) {
                return Result.fail("请勿频繁点击");
            }
            if (!request.getPaymentPassword().equals(UserPool.getUser().getTransactionPassword())) {
                throw new GlobalRunTimeException("支付密码错误");
            }
            taskService.exchangeBox(UserPool.getUser(), request.getId(), request.getNum());
        } catch (InterruptedException e) {
            return Result.fail("请勿频繁点击");
        } finally {
            lock.unlock();
        }


        return Result.success();
    }

    @PostMapping(value = "/boxDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "盲盒详情", notes = "盲盒详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin(required = false)
    public Result<BlindBoxDetailsVO> boxDetail(@RequestBody IdRequest request) {
        UserInfo user = UserPool.getUser();
        BoxTakePool boxTakePool = boxTakePoolDao.getById(request.getId());
        if (ObjectUtil.isNull(boxTakePool)) {
            return Result.fail(ErrorCode.COLLECTION_NOT_FOUND);
        }
        BlindBoxDetailsVO blindBoxDetails = nftMallService.getAllBlindBoxDetails(boxTakePool.getProductBoxId(), null);
        blindBoxDetails.setUpperLimit(boxTakePool.getUpperLimit());
        blindBoxDetails.setPropsName(boxTakePool.getPropsName());
        blindBoxDetails.setVoucherNum(boxTakePool.getCostQuantity());
        if (ObjectUtil.isNotNull(user)) {
            blindBoxDetails.setUserVoucherNum(userEquityPropsService.getHavingCountByUserId(boxTakePool.getPropsId(), EquityPropsTypeEnum.VOUCHER, user.getId()));
        } else {
            blindBoxDetails.setUserVoucherNum(0);
        }


        DigitalCollectionProductInfo digitalCollectionProductInfo = digitalCollectionProductInfoDao.getById(boxTakePool.getProductBoxId());
        //填充可购买数量
        BoxGroupVO boxGroupVO = userCollectionDao.boxGroupUser(user.getId(), digitalCollectionProductInfo.getRelationId(), request.getId());
        blindBoxDetails.setRedeemedQuantity(Objects.isNull(boxGroupVO) ? 0 : boxGroupVO.getCount());

        UserCreatorInfo dao = userCreatorInfoDao.getById(digitalCollectionProductInfo.getUserCreatorId());
        blindBoxDetails.setDaoName(dao.getDaoName());
        blindBoxDetails.setCreatorAvatarImg(dao.getCreatorAvatarImg());
        blindBoxDetails.setIsLockedPosition(digitalCollectionProductInfo.getIsLockedPosition());
        blindBoxDetails.setLockedPositionType(digitalCollectionProductInfo.getLockedPositionType());
        blindBoxDetails.setLockedPositionHour(digitalCollectionProductInfo.getLockedPositionHour());
        blindBoxDetails.setLockedPositionTime(digitalCollectionProductInfo.getLockedPositionTime());
        blindBoxDetails.setLockedPositionDescribe();
        //填充可兑换数
        blindBoxDetails.setSurplusCount();

        blindBoxDetails.setIsRegisterTime(digitalCollectionProductInfo.getIsRegisterTime());
        blindBoxDetails.setRegisterBeginTime(digitalCollectionProductInfo.getRegisterBeginTime());
        blindBoxDetails.setRegisterEndTime(digitalCollectionProductInfo.getRegisterEndTime());

        if (digitalCollectionProductInfo.getIsRegisterTime()) {
            if (user.getCreateTime().after(digitalCollectionProductInfo.getRegisterBeginTime()) && user.getCreateTime().before(digitalCollectionProductInfo.getRegisterEndTime())) {
                blindBoxDetails.setIsConforRegisterTime(Boolean.TRUE);
            }
        }

        return Result.success(blindBoxDetails);
    }

}